401. 二进制手表

链接:https://leetcode-cn.com/problems/binary-watch/

题目描述

二进制手表顶部有 4 个 LED 代表小时(0-11),底部的 6 个 LED 代表分钟(0-59)。
每个 LED 代表一个 0 或 1,最低位在右侧。
Alt text

例如,上面的二进制手表读取 “3:25”。
给定一个非负整数 n 代表当前 LED 亮着的数量,返回所有可能的时间。
案例:

输入: n = 1
返回: [“1:00”, “2:00”, “4:00”, “8:00”, “0:01”, “0:02”, “0:04”, “0:08”, “0:16”, “0:32”]

分析

这是一道比较实际的题目,由于我们不知道具体n为几,所以用回溯算法是比较合适的。

而题目中由于限定了顶部的四个代表了0-11小时,底部的0-59代表分钟。所以我们不用考虑进位的问题。所以当有超过这个限制的,我们需要进行剪枝,否则最后的结果就错了。

递归结构

w代表从nums中选出一个数字。

递归边界

if (n == step)

递归参数

  • n:亮灯数量
  • step:递归层数
  • start:开始节点
  • result:单次结果
  • result_all:最终结果

其他处理

  1. 分别计算小时和分钟,若超过0-11和0-59,则进行剪枝,所以需要写一个函数,判断当前合不合理
  2. 将所有灯组成nums=[1, 2, 4, 8, 1, 2, 4, 8, 16, 32]=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  3. 写一个函数,将nums处理成正确的时间

答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Solution(object):
def __init__(self):
self.result_all = None
self.nums = [1, 2, 4, 8, 1, 2, 4, 8, 16, 32]
self.visited = None

def readBinaryWatch(self, num):
"""
:type num: int
:rtype: List[str]
"""
self.result_all = []
self.visited = [0 for _ in range(len(self.nums))]
self.dfs(num, 0, 0)
return self.result_all

def dfs(self, num, step, start):
if step == num:
self.result_all.append(self.handle_date(self.visited))
return
for i in range(start, len(self.nums)):
self.visited[i] = 1
if not self.calc_sum(self.visited):
self.visited[i] = 0
continue
self.dfs(num, step + 1, i + 1)
self.visited[i] = 0
return

def calc_sum(self, visited):
sum_h = 0
sum_m = 0
for i in range(len(visited)):
if visited[i] == 0:
continue
if i < 4:
sum_h += self.nums[i]
else:
sum_m += self.nums[i]
return 0 <= sum_h <= 11 and 0 <= sum_m <= 59

def handle_date(self, visited):
sum_h = 0
sum_m = 0
for i in range(len(visited)):
if visited[i] == 0:
continue
if i < 4:
sum_h += self.nums[i]
else:
sum_m += self.nums[i]
result = "" + str(sum_h) + ":"
if sum_m < 10:
result += "0" + str(sum_m)
else:
result += str(sum_m)
return result